;;;; init-funcs some functions that are/could be used throughout Emacs
;;;;
;;;; Evgeniy Sharapov, evgeniy.sharapov@gmail.com 
;;;;
;;;;
(eval-when-compile 
	(require 'cl))

(defun my-coding-hook ()
  "Enable things that are convenient across all coding buffers."
  (set (make-local-variable 'comment-auto-fill-only-comments) t)
  (make-local-variable 'column-number-mode)
  (column-number-mode t)
  (setq save-place t)
  (auto-fill-mode) ;; in comments only
  (if window-system (hl-line-mode t))
  (pretty-lambdas)
  (if (functionp 'idle-highlight) (idle-highlight)))

(defun untabify-buffer ()
  "Applies UNTABIFY to the whole buffer"
  (interactive)
  (untabify (point-min) (point-max)))

(defun indent-buffer ()
  "Applies INDENT-REGION to the whole buffer"
  (interactive)
  (indent-region (point-min) (point-max)))

(defun recentf-ido-find-file ()
  "Find a recent file using ido."
  (interactive)
  (let ((file (ido-completing-read "Choose recent file: " recentf-list nil t)))
    (when file
      (find-file file))))

(defun sen:next-user-buffer ()
  "Switch to the next user buffer in cyclic order.\n
User buffers are those not starting with *."
  (interactive)
  (next-buffer)
  (let ((i 0))
    (while (and (string-match "^*" (buffer-name)) (< i 10))
      (setq i (1+ i)) (next-buffer) )))

(defun sen:previous-user-buffer ()
  "Switch to the next user buffer in cyclic order.\n
User buffers are those not starting with *."
  (interactive)
  (previous-buffer)
  (let ((i 0))
    (while (and (string-match "^*" (buffer-name)) (< i 10))
      (setq i (1+ i)) (previous-buffer) )))

(defun sen:next-emacs-buffer ()
  "Switch to the next emacs buffer in cyclic order.\n
Emacs buffers are those starting with *."
  (interactive)
  (next-buffer)
  (let ((i 0))
    (while (and (not (string-match "^*" (buffer-name))) (< i 10))
      (setq i (1+ i)) (next-buffer) )))

(defun sen:previous-emacs-buffer ()
  "Switch to the next user buffer in cyclic order.\n
Emacs buffers are those starting with *."
  (interactive)
  (previous-buffer)
  (let ((i 0))
    (while (and (not (string-match "^*" (buffer-name))) (< i 10))
      (setq i (1+ i)) (previous-buffer) )))

(defun prh:copy-line ()
  "Save current line into Kill-Ring without marking the line "
  (buffer-substring (line-beginning-position) (line-end-position))
  )

(defun prh:check-newline (line)
  "Checks that line ends in newline. Adds it if not."
  (if (eql (aref line (1- (length line))) ?\n)
      line
	(concat line "\n")
	))
(defun prh:count-lines (arg)
  "Count lines depending on arg.
	If arg is positive, count from current position to end,
	if negative, count from start to current position.
	"
  (if (> arg 0)
      (count-lines (point) (point-max))
	(count-lines (point-min) (point)) 1))
	
(defun prh:move-line (&optional arg)
  "Move current line.
	Arg determines number of lines to skip, negative means move up."
  (interactive "p")
  (if (> (prh:count-lines arg) 0)
      (let ((prh:column (current-column)))
        (progn
          (or arg (setq arg 1))
          (forward-line 1)
          (transpose-lines arg)
          (forward-line -1)
          (move-to-column prh:column)))
	))
	
(defun prh:move-line-down (&optional arg)
  "Move current line down. Optional ARG determines number of lines to skip"
  (interactive "p")
  (or arg (setq arg 1))
  (prh:move-line arg)
  )
	
(defun prh:move-line-up (&optional arg)
  "Move current line up. Optional ARG determines number of lines to skip"
  (interactive "p")
  (or arg (setq arg 1))
  (prh:move-line (- arg))
  )
	
(defun prh:duplicate-line (&optional arg)
  "Copy current line.
	Arg determines number of lines to be created and direction."
  (interactive "p")
  (let ((prh:column (current-column)))
	(progn
      (or arg (setq arg 1))
      (if (< arg 0)
          (setq tomove (1+ arg))
        (setq tomove arg))
      (setq prh:cutted-line (prh:copy-line))
      (end-of-line tomove)
      (newline)
      (insert prh:cutted-line)
      (next-line (- arg))
      (move-to-column prh:column)))
  )
	
(defun prh:duplicate-line-down (&optional arg)
  "Duplicate current line down. Optional ARG determines number of lines to skip"
  (interactive "p")
  (or arg (setq arg 1))
  (prh:duplicate-line arg))
	
(defun prh:duplicate-line-up (&optional arg)
  "Duplicate current line up. Optional ARG determines number of lines to skip"
  (interactive "p")
  (or arg (setq arg 1))
  (prh:duplicate-line (- arg))
  )

(defun sen:duplicate-region (beg end &optional dir sep)
  "Duplicates the region either up or down depends on DIR
if DIR greater than 0 then it duplicates it down, otherwise
duplicates it up"
  (let ((p (point))
        (m (mark)))
    (copy-region-as-kill beg end)
    (message "%d" (point))
    (if (> dir 0)
        (goto-char end)
      (goto-char beg))
    (yank)
    (goto-char p)))

(defun sen:duplicate-region-up (beg end &optional sep)
  "Duplicates the region"
  (interactive "*r")
  (let ((p (point)))
    (copy-region-as-kill beg end)
    (message "%d" (point))
    (goto-char end)
    (if (stringp sep) (insert sep))
    (yank)
    (goto-char p)))

(defun sen:duplicate-region-down (beg end &optional sep)
  "Duplicates the region"
  (interactive "*r")
  (let ((p (point)))
    (copy-region-as-kill beg end)
    (message "%d" (point))
    (goto-char end)
    (if (stringp sep) (insert sep))
    (yank)
    (goto-char p)))

(defun sen:duplicate-line-or-region ()
  "duplicate the region if active otherwise the current line"
  (interactive)
  (if mark-active
      (duplicate-region (point) (mark))
    (duplicate-region (point-at-bol) (point-at-eol) "\n")))

(defun open-folder-in-explorer ()  
  "Call when editing a file in a buffer. Open windows explorer in the current directory and select the current file. Windows explorer to go to the file in the current buffer"  
  (interactive)  
  (w32-shell-execute 
   "open" "explorer"  
   (concat "/e,/select," (convert-standard-filename buffer-file-name))
   )
  )

(defvar current-date-time-format "%a %b %d %H:%M:%S %Z %Y"
  "Format of date to insert with `insert-current-date-time' func
See help of `format-time-string' for possible replacements")

(defvar current-time-format "%a %H:%M:%S"
  "Format of date to insert with `insert-current-time' func.
Note the weekly scope of the command's precision.")

(defun insert-current-date-time ()
  "insert the current date and time into current buffer.
Uses `current-date-time-format' for the formatting the date/time."
       (interactive)
       (insert (format-time-string current-date-time-format (current-time)))
       (insert " "))

(defun insert-current-time ()
  "insert the current time (1-week scope) into the current buffer."
       (interactive)
       (insert (format-time-string current-time-format (current-time)))
       (insert " "))

(provide 'init-funcs)
